package com.dog.basics.api.security;


import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.dog.basics.common.constant.CommonConstants;
import com.dog.basics.common.enums.ExceptionCodeEnum;
import com.dog.basics.common.util.RedisUtil;
import com.dog.basics.security.exception.AuthCustomException;
import com.dog.basics.security.exception.BadCredentialsExceptionBase;
import com.dog.basics.security.exception.UsernameNotFoundExceptionBase;
import com.dog.basics.security.exception.WxErrorExceptionBase;
import com.dog.basics.security.provider.AbstractUserDetailsAuthenticationProvider;
import com.dog.basics.security.service.DogUser;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

/**
 * 多登陸
 *
 * @author singingtogether
 */
@ComponentScan
@Component
@AllArgsConstructor
public class MiniAppAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
    private final com.dog.basics.security.service.DogUserDetailsService dogUserDetailsService;
    private final PasswordEncoder passwordEncoder;
    private final WxMpService wxMpService;
    private final WxMaService wxMaService;


    @Override
    protected Authentication createSuccessAuthentication(Authentication authentication, UserDetails user) {
        MiniAppAuthenticationToken result = new MiniAppAuthenticationToken(user, authentication.getCredentials());
        result.setDetails(authentication.getDetails());
        return result;
    }

    @Override
    @ApiOperation(value = "登陆方式账号密码", notes = "登陆方式账号密码", tags = "登陆")
    protected UserDetails retrieveUser(String code, Authentication authentication) throws AuthenticationException {
        DogUser loadedUser = null;
        //获取信息
        String[] strings = null;
        String credentials = null;
        String unionId = null;
        String openId = null;

        MiniAppAuthenticationToken miniAppAuthenticationToken = (MiniAppAuthenticationToken) authentication;
        Integer from = miniAppAuthenticationToken.getType();
        try {
            strings = StrUtil.split(code, "@");
            unionId = miniAppAuthenticationToken.getUnionId().toString();
            openId = miniAppAuthenticationToken.getOpenId().toString();
            credentials = miniAppAuthenticationToken.getCredentials().toString();
        } catch (Exception e) {

        }
        //切开 - 判断什么登录方式
        if (ObjectUtil.isNull(strings) || strings.length <= 1) {
            throw new AuthCustomException("请选择登录方式");
        }

        // 手机号或者邮箱密码登录
        if (StrUtil.equals(strings[0], "passwordOrEmail")) {
            try {
                loadedUser = (DogUser) dogUserDetailsService.loadUserBypasswordOrEmail(strings[1]);
            } catch (UsernameNotFoundExceptionBase var6) {
                throw new UsernameNotFoundExceptionBase("账号不正确");
            }
            String encodedPassword = loadedUser.getPassword();
            String rawPassword = credentials;
            // 密码不正确
            if (!passwordEncoder.matches(rawPassword, encodedPassword)) {
                throw new BadCredentialsExceptionBase("密码不正确");
            }
        }

        // 账号密码登录
        if (StrUtil.equals(strings[0], "password")) {
            try {
                loadedUser = (DogUser) dogUserDetailsService.loadUserByUsername(strings[1]);
            } catch (UsernameNotFoundExceptionBase var6) {
                throw new UsernameNotFoundExceptionBase("账号不正确");
            }
            String encodedPassword = loadedUser.getPassword();
            String rawPassword = credentials;
            // 密码不正确
            if (!passwordEncoder.matches(rawPassword, encodedPassword)) {
                throw new BadCredentialsExceptionBase("密码不正确");
            }
        }
        //SMS 登录
        if (StrUtil.equals(strings[0], "sms")) {
            //判断输入验证信息
            String verificationCode = credentials;
            if (StrUtil.isEmpty(verificationCode)) {
                throw new AuthCustomException("验证码输入为空");
            }
            if (StrUtil.isEmpty(openId)) {
                throw new AuthCustomException("openId输入为空");
            }
            if (StrUtil.isEmpty(unionId)) {
                throw new AuthCustomException("unionId输入为空");
            }
            if (ObjectUtil.isNull(from)) {
                throw new AuthCustomException("from为空");
            }
            Object redisCode = RedisUtil.get(CommonConstants.DEFAULT_CODE_KEY + "SMS@" + strings[1]);
            if (ObjectUtil.isNull(redisCode)) {
                throw new AuthCustomException("验证码超时或未获取验证码");
            }
            String redisVerificationCode = StrUtil.toString(redisCode);
            if (Validator.isFalse(StrUtil.equals(verificationCode, redisVerificationCode))) {
                throw new AuthCustomException("输入验证码错误");
            }
            RedisUtil.del(CommonConstants.DEFAULT_CODE_KEY + "SMS@" + strings[1]);
          //  Boolean openIsOperation = false;
            try {
                loadedUser = (DogUser) dogUserDetailsService.loadUserByWxPhone(strings[1],openId,unionId,from);
            } catch (UsernameNotFoundExceptionBase var6) {
                throw new AuthCustomException(var6.getMessage());
              //  openIsOperation = true;
              //  dogUserDetailsService.insertUserIfNecessary(strings[1], "", 1);

            }
            if (loadedUser == null) {
                loadedUser = (DogUser) dogUserDetailsService.loadUserByUsername(strings[1]);
            }
            // 绑定微信判断
           // if (openIsOperation && StrUtil.isNotBlank(miniAppAuthenticationToken.getOpenId())) {
             //   dogUserDetailsService.insertUserIfNecessary(strings[1], "", 1);
          //  }

        }
        //WXmini登录
/*        if (StrUtil.equals(strings[0], "mini")) {

            WxMaJscode2SessionResult jscode2SessionResult = null;
            //UserConnectAddDto appConnect = new UserConnectAddDto();
            try {
                jscode2SessionResult = wxMaService.jsCode2SessionInfo(strings[1]);
                loadedUser = dogUserDetailsService
                        .loadUserByWxOpenId(jscode2SessionResult.getOpenid(), 1,miniAppAuthenticationToken.getMobile());
            } catch (WxErrorException e) {
                throw new WxErrorExceptionBase(e.getMessage());
            } catch (UsernameNotFoundExceptionBase var6) {
                if (ObjectUtil.isNull(jscode2SessionResult) || ObjectUtil.isNull(jscode2SessionResult.getOpenid())) {
                    throw new WxErrorExceptionBase("获取不到微信opeind");
                }
                //	appConnect.setUserId(loadedUser.getUserId());
                //	appConnect.setAppOpenid(jscode2SessionResult.getUnionid());
                //   dDogUserConnectService.saveObj(appConnect);
                // 返回前端 openId
                // throw new AuthCustomException(ExceptionCodeEnum.WXOPENNULL.getDescription(), ExceptionCodeEnum.WXOPENNULL.getCode(), jscode2SessionResult.getOpenid());
            }
            if (loadedUser == null) {
                loadedUser = (DogUser) dogUserDetailsService.loadUserByWxOpenId(jscode2SessionResult.getOpenid(), 1,miniAppAuthenticationToken.getMobile());
            }

        }*/
//微信小程序 最新
        if (StrUtil.equals(strings[0], "mini")) {
            if (StrUtil.isEmpty(unionId)) {
                throw new AuthCustomException("unionId输入为空");
            }
            if (ObjectUtil.isNull(from)) {
                throw new AuthCustomException("小程序来自哪里为空");
            }
            try {
                loadedUser = dogUserDetailsService
                        .loadUserByWxOpenId(strings[1], 1, unionId,from);
            } catch (UsernameNotFoundExceptionBase var6) {
                if (StrUtil.isBlank(unionId) || StrUtil.isBlank(strings[1])) {
                    throw new WxErrorExceptionBase("获取不到微信opeind");
                }
                //	appConnect.setUserId(loadedUser.getUserId());
                //	appConnect.setAppOpenid(jscode2SessionResult.getUnionid());
                //   dDogUserConnectService.saveObj(appConnect);
                // 返回前端 openId
                // throw new AuthCustomException(ExceptionCodeEnum.WXOPENNULL.getDescription(), ExceptionCodeEnum.WXOPENNULL.getCode(), jscode2SessionResult.getOpenid());
            }
            if (loadedUser == null) {
                loadedUser = (DogUser) dogUserDetailsService.loadUserByWxOpenId(strings[1], 1, unionId,from);
            }

        }
        //WXgzh登录
        if (StrUtil.equals(strings[0], "gzh")) {
            WxMpOAuth2AccessToken accessToken = null;
            WxMpUser wxUser = null;
            //UserConnectAddDto appConnect = new UserConnectAddDto();
            try {
                accessToken = wxMpService.oauth2getAccessToken(strings[1]);
                wxUser = wxMpService.oauth2getUserInfo(accessToken, null);
                loadedUser = dogUserDetailsService
                        .loadUserByWxOpenId(wxUser.getOpenId(), 0, miniAppAuthenticationToken.getMobile(),from);
            } catch (WxErrorException e) {
                throw new WxErrorExceptionBase(e.getMessage());
            } catch (UsernameNotFoundExceptionBase var6) {
                if (ObjectUtil.isNull(accessToken) || ObjectUtil.isNull(wxUser)) {
                    throw new WxErrorExceptionBase("获取不到微信opeind");
                }
                //	appConnect.setUserId(loadedUser.getUserId());
                //	appConnect.setAppOpenid(jscode2SessionResult.getUnionid());
                //   dDogUserConnectService.saveObj(appConnect);
                // 返回前端 openId
                throw new AuthCustomException(ExceptionCodeEnum.WXOPENNULL.getDescription(), ExceptionCodeEnum.WXOPENNULL.getCode(), wxUser.getOpenId());

            }

        }
        //WXApp登录
        if (StrUtil.equals(strings[0], "app")) {
            loadedUser = dogUserDetailsService
                    .loadUserByAppOpenId(strings[1]);
        }
        if (loadedUser == null) {
            throw new AuthCustomException("获取不到用户登录信息");
        }
        if (!loadedUser.isEnabled()) {
            throw new UsernameNotFoundExceptionBase("账号已被锁定,请联系管理员");
        }
        return loadedUser;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return MiniAppAuthenticationToken.class.isAssignableFrom(authentication);
    }

}
